#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "state.h"
#include "stack.h"

#define NULL_ELEMENT (Element *)0

Stack * stackInit(void) {

	Stack* s = (Stack *) malloc(sizeof(Stack));
	if(NULL == s){
		fprintf(stderr, "malloc() in Stack Initialization failed\n");
		exit(EXIT_FAILURE); /* There is no point in going beyond this
		 point */
	}
	s->top = NULL;
	s->size = 0;

	return s;
}

State * stackTop(Stack* s) {

	if(NULL == s){
		fprintf(stderr, "Stack not initialized ?\n");
	}

	if(s->size <= 0){
		return (State *) 0;
	}

	return s->top->value;
}

/*
 * Metoda provede na stacku operaci "pop" - tj. vezme horní prvek, ze stacku
 * ho odstraní a vrátí na něj odkaz.
 */
State *stackPop(Stack * s) {

	Snode * tmp_node = NULL;
	/* pop na prázdný stack je ne-e --> vrátíme null pointer */
	if(s->size <= 0){
		return NULL;
	}

	State *st = s->top->value;
	tmp_node = s->top;
	s->top = s->top->next;
	free(tmp_node);
	s->size--;

	return st;
}

/*
 * Metoda provede na stacku operaci "push" - tj uloží zadaný prvek nahoru na
 * konec stacku.
 */
void stackPush(Stack *s, State *state) {

	if(NULL == s){
		fprintf(stderr, "Stack not initialized ?\n");
	}

	Snode *new = (Snode *) malloc(sizeof(Snode));

	if(NULL == new){
		printf("Out of memory during push!");
		exit(EXIT_FAILURE);
	}
	else if(NULL == s->top){
		s->top = new;

	}
	else{

		new->next = s->top;
		s->top = new; /* push new element onto the top */
	}

	/* nastavíme hodnotu = stav */
	s->top->value = state;
	/* a stack zvětšíme */
	s->size++;
}

/*
 * Vrátí aktuální velikost stacku.
 */
int stackSize(Stack * s) {
	return s->size;
}

void stackDisplay(Stack *s) {
	Snode * tmp;
	tmp = s->top;
	do{
		printState(tmp->value);
		tmp = tmp->next;
	}while (tmp->next != NULL);

}
